﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Opennav.MapGenerator.Map.Labels;
using Opennav.MapGenerator.Map.Locations;
using System.IO;
using Opennav.MapGenerator.Map.MapTiles;
using System.Diagnostics;
using Opennav.MapGenerator.Map.Roads;

namespace Opennav.MapGenerator.Map.Roads
{
    /// <summary>
    /// Fixed size road record.
    /// </summary>
    public class Road
    {
        public static byte HAS_CITY = 0x40;
        public static byte HAS_LABELS = 0x80;
        public static uint LAST_LABEL = 0x80000000;

        private List<Label> _labels = new List<Label>();

        private List<RoadSegment> _segments = new List<RoadSegment>();
        private int _id = -1;
        private int _offset = -1;

        public Road(IList<Label> labels, City city)
        {
            this.City = city;
            foreach (Label label in labels)
            {
                if (!_labels.Contains(label))
                    _labels.Add(label);
            }
        }

        public int Offset
        {
            get
            {
                Debug.Assert(_offset >= 0);
                return _offset;
            }
            set
            {
                _offset = value;
            }
        }

        public int Id
        {
            get
            {
                Debug.Assert(_id >= 0);
                return _id;
            }
            set
            {
                Debug.Assert(_id < 0x1000000);
                this._id = value;
            }
        }

        public City City { get; set; }

        public IList<Label> Labels { get { return _labels; } }

        public IList<RoadSegment> Segments { get { return _segments; } }

        public void Write1(Stream stream)
        {
            BinaryWriter writer = new BinaryWriter(stream);

            byte flags = 0;
            if (Labels.Count > 0)
                flags |= HAS_LABELS;
            if (City != null)
                flags |= HAS_CITY;
            writer.Write(flags);

            if (Labels.Count > 0)
            {
                for (int i = 0; i < Labels.Count; i++)
                {
                    uint labelOffset = (uint)Labels[i].Offset;
                    if (i == Labels.Count - 1)
                        labelOffset |= LAST_LABEL;
                    writer.Write(labelOffset);
                }
            }

            if (City != null)
            {
                writer.Write((byte)(City.Id & 0xff));
                writer.Write((ushort)(City.Id >> 8));
            }

            int dummySegmentOffset = 0;
            writer.Write(dummySegmentOffset);
        }

        public void Write2(Stream stream)
        {
            BinaryWriter writer = new BinaryWriter(stream);
            writer.Seek(1, SeekOrigin.Current);
            if (Labels.Count > 0)
                writer.Seek(4 * Labels.Count, SeekOrigin.Current);
            if (City != null)
                writer.Seek(3, SeekOrigin.Current);
            int segmentOffset = Segments[0].Offset;
            writer.Write(segmentOffset);
        }

        public void WriteIndex(Stream stream)
        {
            BinaryWriter writer = new BinaryWriter(stream);
            writer.Write(Offset);
        }
    }
}
